﻿namespace FiftyOne.Foundation.Mobile.Detection.Wurfl.Handlers
{
    using FiftyOne.Foundation.Mobile.Detection.Wurfl;
    using FiftyOne.Foundation.Mobile.Detection.Wurfl.Matchers.Segment;
    using System;
    using System.Text.RegularExpressions;
    using System.Web;

    internal abstract class RegexSegmentHandler : SegmentHandler
    {
        protected bool _firstMatchOnly;
        protected Regex[] _patterns;
        protected int[] _weights;
        internal const byte CONFIDENCE = 7;
        private const string DEFAULT_PATTERN = "[^ ]+";

        internal RegexSegmentHandler(string regex)
        {
            this._firstMatchOnly = false;
            this.Init(new string[] { regex }, new int[] { 1 }, false);
        }

        internal RegexSegmentHandler(string regex, int[] weights)
        {
            this._firstMatchOnly = false;
            this.Init(new string[] { regex }, weights, false);
        }

        internal RegexSegmentHandler(string[] regexs, int[] weights)
        {
            this._firstMatchOnly = false;
            this.Init(regexs, weights, false);
        }

        internal RegexSegmentHandler(string regex, int[] weights, bool firstMatchOnly)
        {
            this._firstMatchOnly = false;
            this.Init(new string[] { regex }, weights, firstMatchOnly);
        }

        internal RegexSegmentHandler(string[] regexs, int[] weights, bool firstMatchOnly)
        {
            this._firstMatchOnly = false;
            this.Init(regexs, weights, firstMatchOnly);
        }

        protected internal override bool CanHandle(string userAgent)
        {
            foreach (Regex regex in this._patterns)
            {
                if (regex.IsMatch(userAgent))
                {
                    return true;
                }
            }
            return false;
        }

        internal override bool CanHandle(HttpRequest request)
        {
            return this.CanHandle(Provider.GetUserAgent(request));
        }

        internal override Segments CreateSegments(string source)
        {
            if (this._firstMatchOnly)
            {
                return this.CreateSegmentsFirstMatch(source);
            }
            return this.CreateSegmentsMultipleMatches(source);
        }

        private Segments CreateSegmentsFirstMatch(string source)
        {
            Segments segments = new Segments();
            foreach (Regex regex in this._patterns)
            {
                Match match = regex.Match(source);
                if ((match != null) && match.Success)
                {
                    segments.Add(new FiftyOne.Foundation.Mobile.Detection.Wurfl.Matchers.Segment.Segment(match.Value));
                }
                else
                {
                    segments.Add(new FiftyOne.Foundation.Mobile.Detection.Wurfl.Matchers.Segment.Segment(string.Empty));
                }
            }
            return segments;
        }

        private Segments CreateSegmentsMultipleMatches(string source)
        {
            Segments segments = new Segments();
            foreach (Regex regex in this._patterns)
            {
                MatchCollection matchs = regex.Matches(source);
                if (matchs != null)
                {
                    foreach (Match match in matchs)
                    {
                        segments.Add(new FiftyOne.Foundation.Mobile.Detection.Wurfl.Matchers.Segment.Segment(match.Value));
                    }
                }
            }
            return segments;
        }

        internal override int GetSegmentWeight(int index, int numberOfSegments)
        {
            if (index < this._weights.Length)
            {
                return this._weights[index];
            }
            return (numberOfSegments - index);
        }

        private void Init(string[] regexs, int[] weights, bool firstMatchOnly)
        {
            this._patterns = new Regex[regexs.Length];
            for (int i = 0; i < regexs.Length; i++)
            {
                this._patterns[i] = new Regex(regexs[i], RegexOptions.Compiled);
            }
            this._weights = weights;
            this._firstMatchOnly = firstMatchOnly;
        }

        internal override byte Confidence
        {
            get
            {
                return 7;
            }
        }
    }
}

